package cn.edu.zzu.demo04ThreadAdvance;

/**
 * 线程通信： 管程法
 */
public class TestProductConsumer {
    public static void main(String[] args) {
        SynContainer container = new SynContainer();
        new Producer(container,"生产者").start();
        new Consumer(container,"消费者").start();
    }
}

/**
 * 生产者
 */
class Producer extends Thread {
    private SynContainer synContainer ;

    public Producer(SynContainer synContainer,String name) {
        super(name);
        this.synContainer = synContainer;
    }
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            synContainer.push(new Chicken(i));
            System.out.println(Thread.currentThread().getName()+" 生产了 "+i+" 鸡");
        }
    }
}

/**
 * 消费者
 */
class Consumer extends Thread {
    private SynContainer synContainer ;

    public Consumer(SynContainer synContainer,String name) {
        super(name);
        this.synContainer = synContainer;
    }
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            Chicken pop = synContainer.pop(new Chicken(i));
            System.out.println(Thread.currentThread().getName()+" 消费了 "+pop.i+" 鸡");
        }
    }
}

/**
 * 产品
 */
class Chicken {
    int i;

    public Chicken(int i) {
        this.i = i;
    }
}

/**
 * 管程法
 */
class SynContainer {

    //容器
    Chicken[] chickens = new Chicken[10];

    //计算器
    int count = 0 ;

    public synchronized void push(Chicken chicken){
        if (chickens.length-1 <= count){
            //容器满
            try {
                this.wait(); //阻塞该线程
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //存放产品
        chickens[count] = chicken;
        count++ ;

        //产品有了，通知消费者
        this.notify(); //唤醒其他线程
    }

    public synchronized Chicken pop(Chicken chicken){
        if (count <= 0){
            //没有产品
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        //消费
        count-- ;
        chicken = chickens[count];

        //产品消费了， 通知生产者
        this.notify();
        return chicken;
    }
}